#include "login_dialog.h"
#include "ui_login_dialog.h"
#include "visiablelabel.h"
#include <QRegularExpression>
#include <QJsonObject>
#include <QDebug>
#include "configmgr.h"
#include "httpmgr.h"
#include "tcpmgr.h"

Login_Dialog::Login_Dialog(QWidget *parent) :rsacrypt_(new RsaCrypt()),
    QDialog(parent),
    ui(new Ui::Login_Dialog)
{
    ui->setupUi(this);

    //设置默认输入方式为PassWord模式
    ui->pass_edit->setEchoMode(QLineEdit::EchoMode::Password);
    ui->err_tip->setProperty("state","normal");
    repolish(ui->err_tip);
    ui->err_tip->clear();
    //initHandlers();//初始化回调容器
    //外部信号
    connect(HttpMgr::getInstance().get(),&HttpMgr::sig_login_mod_finish,this,
            &Login_Dialog::slot_login_mod_finish);

    //连接tcp管理者发出的登陆失败信号
    connect(TcpMgr::getInstance().get(), &TcpMgr::sig_login_failed, this, &Login_Dialog::slot_login_failed);
    //连接tcp连接请求的信号和槽函数
    connect(this, &Login_Dialog::sig_connect_tcp, TcpMgr::getInstance().get(), &TcpMgr::slot_tcp_connect);
    //连接tcp管理者发出的连接成功信号
    connect(TcpMgr::getInstance().get(), &TcpMgr::sig_con_success, this, &Login_Dialog::slot_tcp_con_finish);

    //自身控件
    connect(ui->register_btn,&QPushButton::clicked,this,&Login_Dialog::switchRegister);
    connect(ui->forget_label,&Visiablelabel::clicked,this,&Login_Dialog::switchResetPass);
    connect(ui->login_btn,&QPushButton::clicked,this,&Login_Dialog::SlotLogin);

    //检查输入是否合理
    connect(ui->user_edit,&QLineEdit::editingFinished,this,[this](){
        checkUserValid();
    });

    connect(ui->pass_edit, &QLineEdit::editingFinished, this, [this](){
        checkPassValid();
    });
}

Login_Dialog::~Login_Dialog()
{
    delete rsacrypt_;
    delete ui;
}

void Login_Dialog::AddTipErr(TipErr te, QString tips)
{
    _tip_errs[te] = tips;
    showTip(tips, false);
}

void Login_Dialog::DelTipErr(TipErr err)
{
    _tip_errs.remove(err);
    if(_tip_errs.empty()){
      ui->err_tip->clear();
      return;
    }
    showTip(_tip_errs.first(), false);
}

bool Login_Dialog::checkUserValid()
{
    if(ui->user_edit->text() == ""){
        AddTipErr(TipErr::TIP_USER_ERR, tr("用户名不能为空"));
        showTip("用户名不能为空",false);
        return false;
    }
    DelTipErr(TipErr::TIP_USER_ERR);
    return true;
}

bool Login_Dialog::checkPassValid()
{
    auto pass = ui->pass_edit->text();
    if(pass.length() < 6 || pass.length()>15){
        //提示长度不准确
        AddTipErr(TipErr::TIP_PWD_ERR, tr("密码长度应为6~15"));
        showTip("密码长度应为6~15",false);
        return false;
    }
    // 创建一个正则表达式对象，按照上述密码要求
    // 这个正则表达式解释：
    // ^[a-zA-Z0-9!@#$%^&*]{6,15}$ 密码长度至少6，可以是字母、数字和特定的特殊字符
    QRegularExpression regExp("^[a-zA-Z0-9!@#$%^&*]{6,15}$");
    bool match = regExp.match(pass).hasMatch();
    if(!match){
        //提示字符非法
        AddTipErr(TipErr::TIP_PWD_ERR, tr("不能包含非法字符"));
        showTip("不能包含非法字符",false);
        return false;;
    }
    DelTipErr(TipErr::TIP_PWD_ERR);
    return true;
}

void Login_Dialog::showTip(QString str, bool is_ok)
{
    if(is_ok)
    {
        ui->err_tip->setProperty("state","normal");
    }
     else
    {
        ui->err_tip->setProperty("state","error");
    }
    ui->err_tip->clear();
    ui->err_tip->setText(str);

    repolish(ui->err_tip);
}

void Login_Dialog::SlotLogin()
{
    bool valid = checkUserValid();
    if(!valid){
        return;
    }

    valid = checkPassValid();
    if(!valid){
        return;
    }

    //发送http请求注册用户
    QJsonObject json_obj;
    json_obj["user"] = ui->user_edit->text();
    QString password = ui->pass_edit->text();
    qDebug() << "原始密码：" << password;
    QString crypt_pass =  rsacrypt_->rsa_pri_encrypt_base64(password);
    qDebug() << "加密密码" << crypt_pass;
    json_obj["passwd"] = crypt_pass;
    crypt_pass =  rsacrypt_->rsa_pub_decrypt_base64(crypt_pass);
    qDebug() << "解密密码" << crypt_pass;

    QString port = ConfigMgr::getInstance()->getGateServerPort();
    QString ip = ConfigMgr::getInstance()->getGateServerIp();
    QString post = ConfigMgr::getInstance()->getPostLogion();
    QString url = "http://" + ip + ":" + port + post;
    qDebug() << url;
    HttpMgr::getInstance()->PostHttpReq(QUrl(url),
                                        json_obj, ReqId::ID_LOGIN,Modules::LOGIN);
}

void Login_Dialog::slot_login_mod_finish(ReqId id, QString str, ErrorCodes er)
{
    if(er != ErrorCodes::SUCCESS){
        showTip(tr("网络请求错误"),false);
        return;
    }
    // 解析 JSON 字符串,res需转化为QByteArray
    QJsonDocument jsonDoc = QJsonDocument::fromJson(str.toUtf8());
    //json解析错误
    if(jsonDoc.isNull()){
        showTip(tr("json解析错误"),false);
        return;
    }
    //json解析错误
    if(!jsonDoc.isObject()){
        showTip(tr("json解析错误"),false);
        return;
    }
    QJsonObject jsonObj = jsonDoc.object();

    int error = jsonObj["error"].toInt();
    switch (error) {
            case ErrorCodes::SUCCESS:
                showTip("登录成功",true);
                break;
            case ErrorCodes::UserNotMatch:
                showTip("用户不存在,点击注册按钮进行注册",false);
                return;
            case ErrorCodes::PasswdErr:
                showTip("密码错误",false);
                return;
            default:
                showTip("未知错误",false);
                return;
            }

    auto user = jsonObj["user"].toString();
            //发送信号通知tcpMgr发送长链接
            ServerInfo si;
            si.Uid = jsonObj["uid"].toInt();
            si.Host = jsonObj["host"].toString();
            si.Port = jsonObj["port"].toString();
            si.Token = jsonObj["token"].toString();
            _uid = si.Uid;
            _token = si.Token;
            qDebug()<< "user is " << user << " uid is " << si.Uid <<" host is "
                    << si.Host << " Port is " << si.Port << " Token is " << si.Token;
            emit sig_connect_tcp(si);
            return;
}

void Login_Dialog::slot_tcp_con_finish(bool bsuccess)
{
   if(bsuccess){
      showTip(tr("聊天服务连接成功，正在登录..."),true);
      QJsonObject jsonObj;
      jsonObj["uid"] = _uid;
      jsonObj["token"] = _token;
      QJsonDocument doc(jsonObj);
      QString jsonString = doc.toJson(QJsonDocument::Indented);
      //发送tcp请求给chat server
      TcpMgr::getInstance()->sig_send_data(ReqId::ID_CHAT_LOGIN, jsonString);
   }else{
      showTip(tr("网络异常"),false);
      //enableBtn(true);
   }
}

void Login_Dialog::slot_login_failed(int err)
{
    QString result = QString("登录失败, err is %1").arg(err);
    showTip(result,false);
    //enableBtn(true);
}
